home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************\
- ** ________________________________ **
- ** A n t h o n y |________ __ __ ________| **
- ** | |o_| |o_| | **
- ** T h y s s e n __| __ __ |__ **
- ** __| __| | | |__ |__ **
- ** `` Dragon Computing ! '' __| __| | | |__ |__ **
- ** |_____| |__| |_____| **
- ** **
- \*********************************************************************/
- /* Given individual menu entries (Menu,Item,SubItem,CommandChar),
- ** add them to the MPort as Extended Menu Items.
- ** Calculate positioning information required to complete the menus.
- */
- #include "AMenu.h"
- #include "AllocStr.h" /* string copy/allocate/deallocate macros */
- #include <Graphics/GfxBase.h> /* so we can get the font width and height */
-
- unsigned WBMenus, NextGap, MenuGap; /* Number WB menus, Menu Pos */
- UBYTE Color[]={2,1}, TColor[]={2,3}; /* Colors :- Items and Title */
- USHORT ItemStyle = HIGHCOMP; /* MenuItem Highlighting style */
- UWORD FontWidth, FontHeight; /* size of font in use */
-
- struct ExtMenuItem **EItemList; /* Last ExtMenuItem in EItemList */
- struct Menu **MenuList, *CurrMenu;
- struct MenuItem **OldItemList, **ItemList, *CurrSubMenu;
- unsigned OldItemPos, ItemPos;
-
- DB( int NumMenus; int NumItems; ) /* Debugging variables - memory checks */
-
-
- /* NOTE: The TopEdge entry in the head element of a menu or sub-menu
- ** is used to store information about the column structure of that
- ** menu. The macros that follow, map this information in to, and out
- ** of this store.
- */
- #define SHIFTCOLS(n) ((n)&255)
- #define SHIFTPOS(n) (((n)&255)<<8)
- #define NUMCOLS(n) ((n)&255)
- #define NUMPOS(n) (((n)>>8)&255)
-
- /* The LeftEdge entry in individual items (including the sub-menu head
- ** item) is used to hold the position number of that item in the final
- ** columned array of the menu.
- */
-
- /*---------------------------------------------------------------*/
-
-
- void
- StartMenu()
- /* Initialise the facts needed */
- {
- struct Menu *Menu;
- ULONG Ilock;
-
- M->AMenu = NULL;
- MenuList = &M->AMenu;
- M->EItemList = NULL;
- EItemList = &M->EItemList;
- FontWidth = GfxBase->DefaultFont->tf_XSize; /* font size */
- FontHeight = GfxBase->DefaultFont->tf_YSize;
-
- Ilock = LockIBase(0L);
- Menu = M->WBWindow->MenuStrip; /* The First WB Menu */
- MenuGap = Menu->NextMenu->LeftEdge -
- (Menu->LeftEdge + Menu->Width); /* The Gap between WB Menus */
- for( WBMenus=1; Menu->NextMenu; Menu=Menu->NextMenu) /* Count WB Menus */
- WBMenus++;
- NextGap = Menu->LeftEdge + Menu->Width; /* Start of Next Menu Gap */
- UnlockIBase(Ilock);
-
- DB( NumMenus = NumItems = 0; )
- }
-
-
- static void
- PositionMenu(ItemList, SavedInfo, Top, Left)
- struct MenuItem *ItemList;
- unsigned SavedInfo, Top, Left;
- /* Given an ItemList organise it into a number of Columns
- ** Offset by Top and Left (for SubMenus).
- ** Assumes that LeftEdge contains the Position Number for
- ** each Item in Item List.
- */
- {
- struct MenuItem *Start, *End; /* Position within ItemList */
- unsigned NumColumns, ItemsPerColumn, Column;
-
- NumColumns = NUMCOLS(SavedInfo);
- ItemsPerColumn = NUMPOS(SavedInfo) / NumColumns + 1;
-
- End = ItemList;
-
- for(Column=0; Column<NumColumns; Column++ ) {
- SHORT Width, ColWidth=0;
-
- Start = End; /* first Item in column = End of last Column */
-
- /* determine Columns Width and Extent */
- while( End && (End->LeftEdge/ItemsPerColumn) == Column ) {
- Width = End->Width;
- if( End->Flags & COMMSEQ )
- Width += COMMWIDTH + FontWidth + 4;
- if( Width > ColWidth )
- ColWidth = Width;
-
- End = End->NextItem;
- }
-
- /* Position all the Items in Column */
- while( Start != End ) {
-
- /* if their a Sub-Menu within this menu - Position it*/
- if( Start->SubItem )
- PositionMenu( Start->SubItem, Start->TopEdge, 0, ColWidth );
-
- /* position this Item */
- Start->TopEdge = Top +
- (Start->LeftEdge % ItemsPerColumn) * (FontHeight+2);
- Start->LeftEdge = Left;
- Start->Width = ColWidth;
-
- Start = Start->NextItem;
- }
-
- Left = Left + ColWidth + 8; /* Gap between columns */
- } /* For each Column */
-
- }
-
-
- BOOL
- FinishMenu()
- /* Cleanup New Menus - Postition, Size, etc. */
- {
- struct Menu *Menu;
- BOOL ScreenOverflow;
-
- DB( Printf("Added -- %ld Menus, %ld Items\n", NumMenus, NumItems); )
-
- ScreenOverflow = ( NextGap > M->WBWindow->Width );
- /* screen overflow on number of menus ? */
-
- for (Menu = M->AMenu; Menu; Menu=Menu->NextMenu) {
- PositionMenu( Menu->FirstItem, Menu->TopEdge, 0, 0 );
- Menu->TopEdge = 0; /* explictly remove information saved */
- }
-
- return ScreenOverflow; /* if overflow - have parser WARN user */
- }
-
-
- /*---------------------------------------------------------------------*/
-
- /* create and initialize a new menu item */
- struct ExtMenuItem *
- AddItem(ItemName, CommandChar)
- char *ItemName, CommandChar;
- {
- register struct ExtMenuItem *EItem;
- register struct MenuItem *Item;
- register struct IntuiText *IText;
-
- EItem = (struct ExtMenuItem *)
- AllocMem(sizeof(struct ExtMenuItem), MEMF_PUBLIC|MEMF_CLEAR);
- IText = (struct IntuiText *)
- AllocMem(sizeof(struct IntuiText), MEMF_PUBLIC|MEMF_CLEAR);
- Item = (struct MenuItem *)EItem; /* same object different type */
-
- /* fill out the selection */
- IText->FrontPen = Color[0];
- IText->BackPen = Color[1];
- IText->DrawMode = JAM2;
- IText->IText = (UBYTE*)AllocStr(ItemName);
- Item->Height = FontHeight;
- Item->Width = IntuiTextLength(IText);
- Item->Flags = ITEMTEXT | ITEMENABLED | ItemStyle;
- Item->ItemFill = (APTR)IText;
- if( CommandChar ) {
- Item->Command = CommandChar;
- Item->Flags |= COMMSEQ;
- }
-
- *EItemList = EItem; /* add to EItemList for Free'ing */
- EItemList = &EItem->NextEItem;
-
- *ItemList = Item; /* add to the current MenuItem chain */
- ItemList = &Item->NextItem;
- Item->LeftEdge = ItemPos++;
-
- DB( NumItems++; )
- return EItem;
- }
-
-
- void
- AddTitle( TitleName )
- char *TitleName;
- /* create a Menu Item in the form of a Title
- */
- {
- struct ExtMenuItem *EItem = AddItem( TitleName, '\0' );
- struct IntuiText *IText =
- (struct IntuiText *)EItem->MenuItem.ItemFill;
- IText->FrontPen = TColor[0];
- IText->BackPen = TColor[1];
- EItem->MenuItem.Flags = ITEMTEXT | ITEMENABLED | HIGHNONE;
- }
-
-
- void
- AddSkip()
- /* skip a position in the Menu Items (Leave a space)
- */
- {
- ItemPos++; /* adjust position number for latter items and menu size */
- }
-
-
- /*-------------------------------------------------------------*/
-
- void
- AddSubMenu(SubName, NumColumns)
- char *SubName;
- int NumColumns;
- {
- struct ExtMenuItem *EItem = AddItem(SubName, '\0');
- struct MenuItem *Item = (struct MenuItem *)EItem;
-
- Item->TopEdge = SHIFTCOLS(NumColumns); /* store information needed */
-
- CurrSubMenu = Item;
- OldItemList = ItemList; /* setup item list */
- ItemList = &Item->SubItem;
- OldItemPos = ItemPos;
- ItemPos = 0;
- }
-
-
- void
- EndSubMenu()
- /* Cleanup and finalize a SubMenu */
- {
- CurrSubMenu->TopEdge |= SHIFTPOS(ItemPos-1); /* last position number */
- ItemPos = OldItemPos; /* return to a normal Menu */
- ItemList = OldItemList;
- }
-
- /*------------------------------------------------------------*/
-
- void
- AddMenu(MenuName, NumColumns)
- char *MenuName;
- int NumColumns;
- /* Start a new menu attaching it to the AMenu list and storing
- ** Information about its characteristics
- */
-
- {
- struct Menu *Menu = (struct Menu *)
- AllocMem(sizeof(struct Menu), MEMF_PUBLIC|MEMF_CLEAR);
-
- Menu->MenuName = (UBYTE *)AllocStr(MenuName);
- Menu->LeftEdge = NextGap + MenuGap; /* use menugap on creation */
- Menu->Width = (strlen(MenuName)+1) * FontWidth;
- Menu->Flags = MENUENABLED;
- NextGap = Menu->LeftEdge + Menu->Width;
- Menu->TopEdge = SHIFTCOLS(NumColumns);
-
- CurrMenu = Menu;
- *MenuList = Menu; /* add to menu list */
- MenuList = &Menu->NextMenu;
- ItemList = &Menu->FirstItem; /* initialize Item list */
- ItemPos = 0;
-
- DB( NumMenus++; );
- }
-
-
- void
- EndMenu()
- /* Finalize the Position Tally for this Menu */
- {
- CurrMenu->TopEdge |= SHIFTPOS(ItemPos-1); /* last position number */
- }
-
- /*------------------------------------------------------------*/
-
- void
- FreeMenus()
- /* free up all space taken up by our menus */
- {
- struct Menu *Menu;
- struct ExtMenuItem *EItem;
- struct IntuiText *IText;
-
- DB( NumMenus = NumItems = 0; )
-
- while( EItem = M->EItemList ) { /* free all the ExtMenuItems */
- M->EItemList = EItem->NextEItem;
- if( EItem->Cmd ) FreeStr(EItem->Cmd);
- if( EItem->Args ) FreeStr(EItem->Args);
- if( EItem->Console ) FreeStr(EItem->Console);
- if( EItem->Directory ) FreeStr(EItem->Directory);
- IText = (struct IntuiText *)EItem->MenuItem.ItemFill;
- FreeStr(IText->IText);
- FreeMem(IText, sizeof(struct IntuiText));
- FreeMem(EItem, sizeof(struct ExtMenuItem));
- DB( NumItems++; )
- }
-
- while( Menu = M->AMenu ) { /* Free all the Menus */
- M->AMenu = Menu->NextMenu;
- FreeStr(Menu->MenuName);
- FreeMem(Menu, sizeof(struct Menu));
- DB( NumMenus++; )
- }
- DB( Printf("\nFreed -- %ld Menus, %ld Items\n", NumMenus, NumItems); )
- }
-
-